package com.cdyurui.core;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import com.cdyurui.exception.CheckerException;

/**
 * API调用入口类
 * 
 * @author motianlong Email：923197919@qq.com
 * @date 2018年5月19日 上午9:54:28
 * @jdk 1.8
 */
public class ObjChecker {
	/**
	 * 核心检查方法，遇到检查不通过的字段，会把该字段放入CheckResult的errorFields中，并继续检查其他字段
	 * 
	 * @author motianlong
	 * @date 2018年5月19日
	 * @param object->需要检查的对象
	 * @return 检查结果
	 */
	public CheckResult check(Object object) {
		return check(object, false);
	}

	/**
	 * 核心检查方法，如果exceptionFlag为false,遇到检查不通过的字段，会把该字段放入ErrorField中，并继续检查其他字段
	 * 如果exceptionFlag为true,遇到检查不通过的字段,立即抛出CheckerException异常
	 * 
	 * @param object
	 * @param exceptionFlag
	 * @return
	 * @author motianlong
	 * @date 2018年5月19日
	 */
	public CheckResult check(Object object, boolean exceptionFlag) {
		CheckResult checkResult = new CheckResult();
		if (null == object) {
			throw new NullPointerException();
		}
		Class<?> clazz = object.getClass();
		Field[] fields = clazz.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			field.setAccessible(true);
			Object value = null;
			try {
				value = field.get(object);
			} catch (Exception e) {
				throw new CheckerException(e);
			}
			if (field.isAnnotationPresent(com.cdyurui.annotation.check.class)) {
				com.cdyurui.annotation.check annotation = field.getAnnotation(com.cdyurui.annotation.check.class);
				boolean require = annotation.require();
				int maxLenth = annotation.lenth();
				boolean isNumber = annotation.isNumber();
				boolean isEnum = annotation.isEnum();
				String[] enumeration = annotation.enumeration();
				String regex = annotation.regex();
				// 检查是否必输
				if (require) {// 必输检查
					if (!checkRequire(value)) {// 没有输入
						fillErrorResult("该字段不能为空", checkResult, field, exceptionFlag);
					}
				}
				// 检查字段长度
				if (-1 != maxLenth && value != null && !"".equals(value) && ObjectType.STRING == getType(value)) {
					String string = (String) value;
					if (string.length() > maxLenth) {
						fillErrorResult("该字段长度超出", checkResult, field, exceptionFlag);
					}
				}
				// 检查是否为数字
				if (isNumber) {
					if (value != null && !"".equals(value) && ObjectType.STRING == getType(value)) {
						String string = (String) value;
						if (!checkIsNumber(string)) {
							fillErrorResult("该字段必须为数字类型", checkResult, field, exceptionFlag);
						}
					}
				}
				// 检查是否为枚举类型
				if (isEnum) {
					if (enumeration == null || enumeration.length == 0) {
						throw new CheckerException("未指定枚举值！请指定check注解enumeration值！");
					}
					if (value != null && !"".equals(value) && ObjectType.STRING == getType(value)) {
						String string = (String) value;
						List<String> asList = Arrays.asList(enumeration);
						if (!asList.contains(string)) {
							fillErrorResult("该字段非法，必须为枚举值" + asList, checkResult, field, exceptionFlag);
						}
					}
				}
				// 自定义类型检查
				if (null != value && !"".equals(value) && regex != null && !"".equals(regex)
						&& ObjectType.STRING == getType(value)) {
					String string = (String) value;
					if (!string.matches(regex)) {
						fillErrorResult("该字段不满足正则表达式\"" + regex + "\"", checkResult, field, exceptionFlag);
					}
				}
			}
		}
		return checkResult;
	}

	private void errorHanlder(boolean exceptionFlag, String errorMsg) {
		if (exceptionFlag) {
			throw new CheckerException(errorMsg);
		}
	}

	private boolean checkRequire(Object object) {
		if (null == object) {
			return false;
		}
		ObjectType objectType = getType(object);
		if (ObjectType.COLLECTION == objectType) {
			Collection<?> collection = (Collection<?>) object;
			if (collection.size() == 0) {
				return false;
			}
		} else if (ObjectType.STRING == objectType) {
			String string = (String) object;
			if ("".equals(string.trim())) {
				return false;
			}
		}
		return true;
	}

	private boolean checkIsNumber(String string) {
		if (string.endsWith("\\.")) {
			return false;
		}
		return string.matches("^[0-9]+\\.*[0-9]*$");
	}

	private ObjectType getType(Object object) {
		if (object instanceof Collection) {
			return ObjectType.COLLECTION;
		} else if (object instanceof String) {
			return ObjectType.STRING;
		} else {
			throw new CheckerException("暂不支持该类型的检查！[" + object.getClass().getName() + "]");
		}
	}

	private void fillErrorResult(String errorMsg, CheckResult checkResult, Field field, boolean exceptionFlag) {
		String key = field.getAnnotation(com.cdyurui.annotation.check.class).name() + "[" + field.getName() + "]";// 返回List中的值
		checkResult.setResult(false);
		errorHanlder(exceptionFlag, errorMsg + ":" + key);
		ErrorFiled errorFiled = new ErrorFiled(field.getName(), errorMsg + ":" + key);
		checkResult.getErrorFields().add(errorFiled);
	}

}
